package com.halfsword.creativecraft.block.custom.machine.blockentity.modules;

import com.halfsword.creativecraft.modules.BaseFluidTank;
import com.halfsword.creativecraft.modules.interfaces.IFluidHandlerFacet;
import net.minecraft.core.BlockPos;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraftforge.fluids.FluidStack;
import net.minecraftforge.fluids.capability.IFluidHandler;
import net.minecraftforge.common.util.LazyOptional;

import java.util.function.Predicate;

/**
 * 流体处理模块实现
 * 负责管理机器的流体槽位和流体处理逻辑
 */
public class FluidHandlerModule implements IFluidHandlerFacet {

    private final String moduleId;
    private final BaseFluidTank[] fluidTanks;
    private final LazyOptional<IFluidHandler> fluidHandler;

    public FluidHandlerModule(String moduleId, int tankCount, int tankCapacity, Predicate<FluidStack> validator) {
        this.moduleId = moduleId;
        this.fluidTanks = createFluidTanks(tankCount, tankCapacity, validator);
        this.fluidHandler = LazyOptional.of(this::createFluidHandler);
    }

    @Override
    public String getModuleId() {
        return moduleId;
    }

    @Override
    public void tick(Level level, BlockPos pos, BlockState state) {
        // 流体处理模块的tick逻辑
        // 可以在这里实现流体传输或消耗逻辑
    }

    @Override
    public void onUnload() {
        // 释放流体处理器
        fluidHandler.invalidate();
    }

    @Override
    public BaseFluidTank[] getFluidTanks() {
        return fluidTanks;
    }

    @Override
    public LazyOptional<IFluidHandler> getFluidHandler() {
        return fluidHandler;
    }

    protected BaseFluidTank[] createFluidTanks(int count, int capacity, Predicate<FluidStack> validator) {
        BaseFluidTank[] tanks = new BaseFluidTank[count];
        for (int i = 0; i < count; i++) {
            tanks[i] = new BaseFluidTank("Tank_" + i, capacity, validator);
        }
        return tanks;
    }

    protected IFluidHandler createFluidHandler() {
        return new IFluidHandler() {
            @Override
            public int getTanks() {
                return fluidTanks.length;
            }

            @Override
            public FluidStack getFluidInTank(int tank) {
                if (tank < 0 || tank >= fluidTanks.length) {
                    return FluidStack.EMPTY;
                }
                return fluidTanks[tank].getFluid();
            }

            @Override
            public int getTankCapacity(int tank) {
                if (tank < 0 || tank >= fluidTanks.length) {
                    return 0;
                }
                return fluidTanks[tank].getCapacity();
            }

            @Override
            public boolean isFluidValid(int tank, FluidStack stack) {
                if (tank < 0 || tank >= fluidTanks.length) {
                    return false;
                }
                return fluidTanks[tank].isFluidValid(stack);
            }

            @Override
            public int fill(FluidStack resource, FluidAction action) {
                if (resource.isEmpty() || !isFluidValid(0, resource)) {
                    return 0;
                }

                int filled = 0;
                FluidStack remaining = resource.copy();

                // 尝试填充所有槽位
                for (BaseFluidTank tank : fluidTanks) {
                    int amount = tank.fill(remaining, action);
                    filled += amount;
                    if (amount > 0) {
                        remaining.shrink(amount);
                        if (remaining.isEmpty()) {
                            break;
                        }
                    }
                }

                return filled;
            }

            @Override
            public FluidStack drain(FluidStack resource, FluidAction action) {
                if (resource.isEmpty()) {
                    return FluidStack.EMPTY;
                }

                FluidStack drained = FluidStack.EMPTY;
                FluidStack toDrain = resource.copy();

                // 尝试从所有槽位抽取
                for (int i = fluidTanks.length - 1; i >= 0; i--) {
                    BaseFluidTank tank = fluidTanks[i];
                    if (tank.getFluid().isFluidEqual(toDrain)) {
                        FluidStack partialDrained = tank.drain(toDrain, action);
                        if (!partialDrained.isEmpty()) {
                            if (drained.isEmpty()) {
                                drained = partialDrained.copy();
                            } else {
                                drained.grow(partialDrained.getAmount());
                            }
                            toDrain.shrink(partialDrained.getAmount());
                            if (toDrain.isEmpty()) {
                                break;
                            }
                        }
                    }
                }

                return drained;
            }

            @Override
            public FluidStack drain(int maxDrain, FluidAction action) {
                if (maxDrain <= 0) {
                    return FluidStack.EMPTY;
                }

                FluidStack drained = FluidStack.EMPTY;
                int remaining = maxDrain;

                // 尝试从所有槽位抽取
                for (int i = fluidTanks.length - 1; i >= 0; i--) {
                    BaseFluidTank tank = fluidTanks[i];
                    if (!tank.getFluid().isEmpty()) {
                        FluidStack partialDrained = tank.drain(remaining, action);
                        if (!partialDrained.isEmpty()) {
                            if (drained.isEmpty()) {
                                drained = partialDrained.copy();
                            } else if (drained.isFluidEqual(partialDrained)) {
                                drained.grow(partialDrained.getAmount());
                            } else {
                                // 不同类型的流体，停止抽取
                                break;
                            }
                            remaining -= partialDrained.getAmount();
                            if (remaining <= 0) {
                                break;
                            }
                        }
                    }
                }

                return drained;
            }
        };
    }

    /**
     * 将模块数据保存到NBT
     * @param tag 要保存到的CompoundTag
     */
    public void saveToNBT(CompoundTag tag) {
        CompoundTag fluidTanksTag = new CompoundTag();
        for (int i = 0; i < fluidTanks.length; i++) {
            CompoundTag tankTag = new CompoundTag();
            fluidTanks[i].writeToNBT(tankTag);
            fluidTanksTag.put("Tank" + i, tankTag);
        }
        tag.put("FluidTanks", fluidTanksTag);
    }

    /**
     * 从NBT加载模块数据
     * @param tag 包含数据的CompoundTag
     */
    public void loadFromNBT(CompoundTag tag) {
        if (tag.contains("FluidTanks")) {
            CompoundTag fluidTanksTag = tag.getCompound("FluidTanks");
            for (int i = 0; i < fluidTanks.length; i++) {
                if (fluidTanksTag.contains("Tank" + i)) {
                    CompoundTag tankTag = fluidTanksTag.getCompound("Tank" + i);
                    fluidTanks[i].readFromNBT(tankTag);
                }
            }
        }
    }

    /**
     * 获取模块数据的唯一标识符
     * @return 模块数据标识符
     */
    public String getDataKey() {
        return "fluid_handler_" + moduleId;
    }
}